home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigarom 1
/
Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso
/
FILES
/
DEV
/
I-Z
/
XLISP.cpt
/
XLisp ƒ
/
XLISP folder
/
pp.lsp
< prev
next >
Wrap
Text File
|
1988-04-21
|
11KB
|
334 lines
; PP.LSP -- a pretty-printer for XLISP.
; Adapted by Jim Chapman (Bix: jchapman) from a program written originally
; for IQLISP by Don Cohen. Copyright (c) 1984, Don Cohen; (c) 1987, Jim
; Chapman. Permission for non-commercial use and distribution is hereby
; granted. Modified for XLISP 2.0 by David Betz.
; In addition to the pretty-printer itself, this file contains a few functions
; that illustrate some simple but useful applications.
; The basic function accepts two arguments:
; (PP OBJECT STREAM)
; where OBJECT is any Lisp expression, and STREAM optionally specifies the
; output (default is *standard-output*).
; PP-FILE pretty-prints an entire file. It is what I used to produce this
; file (before adding the comments manually). The syntax is:
; (PP-FILE "filename" STREAM)
; where the file name must be a string or quoted, and STREAM, again, is the
; optional output destination.
; PP-DEF works just like PP, except its first argument is assumed to be the
; name of a function or macro, which is translated back into the original
; DEFUN or DEFMACRO form before printing.
; MISCELLANEOUS USAGE AND CUSTOMIZATION NOTES:
; 1. The program uses tabs whenever possible for indentation.
; This greatly reduces the cost of the blank space. If your output
; device doesn't support tabs, set TABSIZE to NIL -- which is what I
; did when I pretty-printed this file, because of uncertainty
; about the result after uploading.
; 2. Printmacros are used to handle special forms. A printmacro is not
; really a macro, just an ordinary lambda form that is stored on the
; target symbol's property list. The default printer handles the form
; if there is no printmacro or if the printmacro returns NIL.
; 3. Note that all the pretty-printer subfunctions, including the
; the printmacros, return the current column position.
; 4. Miser mode is not fully implemented in this version, mainly because
; lookahead was too slow. The idea is, if the "normal" way of
; printing the current expression would exceed the right margin, then
; use a mode that conserves horizontal space.
; 5. When PP gets to the last 8th of the line and has more to print than
; fits on the line, it starts near the left margin. This is not
; wonderful, but neither are the alternatives. If you have a better
; idea, go for it.
; 6. Storage requirements are about 1450 cells to load.
; 7. I tested this with XLISP 1.7 on an Amiga.
;(DEFUN SYM-FUNCTION (X) ;for Xlisp 1.7
; (CAR (SYMBOL-VALUE X)))
(DEFUN SYM-FUNCTION (X) ;for Xlisp 2.0
(GET-LAMBDA-EXPRESSION (SYMBOL-FUNCTION X)))
(SETQ TABSIZE 8) ;set this to NIL for no tabs
(SETQ MAXSIZE 50) ;for readability, PP tries not to print more
;than this many characters on a line
(SETQ MISER-SIZE 2) ;the indentation in miser mode
(SETQ MIN-MISER-CAR 4) ;used for deciding when to use miser mode
(SETQ MAX-NORMAL-CAR 9) ;ditto
; The following function prints a file
(DEFUN PP-FILE (FILENAME &OPTIONAL STREAMOUT)
(OR STREAMOUT (SETQ STREAMOUT *STANDARD-OUTPUT*))
(PRINC "; Listing of " STREAMOUT)
(PRINC FILENAME STREAMOUT)
(TERPRI STREAMOUT)
(TERPRI STREAMOUT)
(DO* ((FP (OPENI FILENAME)) (EXPR (READ FP) (READ FP)))
((NULL EXPR) (CLOSE FP))
(PP EXPR STREAMOUT)
(TERPRI STREAMOUT)))
; Print a lambda or macro form as a DEFUN or DEFMACRO:
(DEFMACRO PP-DEF (WHO &OPTIONAL STREAM)
`(PP (MAKE-DEF ,WHO) ,STREAM))
(DEFMACRO MAKE-DEF (NAME &AUX EXPR TYPE)
(SETQ EXPR (SYM-FUNCTION NAME))
(SETQ TYPE
(CADR (ASSOC (CAR EXPR)
'((LAMBDA DEFUN) (MACRO DEFMACRO)))))
(LIST 'QUOTE
(APPEND (LIST TYPE NAME) (CDR EXPR))))
; The pretty-printer high level function:
(DEFUN PP (X &OPTIONAL STREAM)
(OR STREAM (SETQ STREAM *STANDARD-OUTPUT*))
(PP1 X STREAM 1 80)
(TERPRI STREAM)
T)
(DEFUN PP1 (X STREAM CURPOS RMARGIN &AUX SIZE POSITION WIDTH)
(COND ((NOT (CONSP X)) (PRIN1 X STREAM) (+ CURPOS (FLATSIZE X)))
((PRINTMACROP X STREAM CURPOS RMARGIN))
((AND (> (FLATSIZE X) (- RMARGIN CURPOS))
(< (* 8 (- RMARGIN CURPOS)) RMARGIN))
(SETQ SIZE (+ (/ RMARGIN 8) (- CURPOS RMARGIN)))
(MOVETO STREAM CURPOS SIZE)
(SETQ POSITION (PP1 X STREAM SIZE RMARGIN))
(MOVETO STREAM POSITION SIZE))
(T (PRINC "(" STREAM)
(SETQ POSITION
(PP1 (CAR X) STREAM (1+ CURPOS) RMARGIN))
(COND ((AND (>= (SETQ WIDTH (- RMARGIN POSITION))
(SETQ SIZE (FLATSIZE (CDR X))))
(<= SIZE MAXSIZE))
(PP-REST-ACROSS (CDR X) STREAM POSITION RMARGIN))
((CONSP (CAR X))
(MOVETO STREAM POSITION CURPOS)
(PP-REST (CDR X) STREAM CURPOS RMARGIN))
((> (- POSITION CURPOS) MAX-NORMAL-CAR)
(MOVETO STREAM POSITION (+ CURPOS MISER-SIZE))
(PP-REST (CDR X) STREAM (+ CURPOS MISER-SIZE) RMARGIN))
(T (PP-REST (CDR X) STREAM POSITION RMARGIN))))))
; MOVETO controls indentating and tabbing.
(DEFUN MOVETO (STREAM CURPOS GOALPOS)
(COND ((> CURPOS GOALPOS)
(TERPRI STREAM)
(SETQ CURPOS 1)
(IF TABSIZE
(DO NIL
((< (- GOALPOS CURPOS) TABSIZE))
(PRINC "\t" STREAM)
(SETQ CURPOS (+ CURPOS TABSIZE))))))
(SPACES (- GOALPOS CURPOS) STREAM)
GOALPOS)
(DEFUN SPACES (N STREAM)
(DOTIMES (I N) (PRINC " " STREAM)))
(DEFUN PP-REST-ACROSS (X STREAM CURPOS RMARGIN &AUX POSITION)
(SETQ POSITION CURPOS)
(PROG NIL
LP
(COND ((NULL X) (PRINC ")" STREAM) (RETURN (1+ POSITION)))
((NOT (CONSP X))
(PRINC " . " STREAM)
(PRIN1 X STREAM)
(PRINC ")" STREAM)
(RETURN (+ 4 POSITION (FLATSIZE X))))
(T (PRINC " " STREAM)
(SETQ POSITION
(PP1 (CAR X) STREAM (1+ POSITION) RMARGIN))
(SETQ X (CDR X))
(GO LP)))))
(DEFUN PP-REST (X STREAM CURPOS RMARGIN &AUX POSITION POS2)
(SETQ POSITION CURPOS)
(PROG NIL
LP
(COND ((NULL X) (PRINC ")" STREAM) (RETURN (1+ POSITION)))
((NOT (CONSP X))
(AND (> (FLATSIZE X) (- (- RMARGIN POSITION) 3))
(SETQ POSITION (MOVETO STREAM POSITION CURPOS)))
(PRINC " . " STREAM)
(PRIN1 X STREAM)
(PRINC ")" STREAM)
(RETURN (+ POSITION 4 (FLATSIZE X))))
((AND (NOT (CONSP (CAR X)))
(<= (SETQ POS2 (+ 1 POSITION (FLATSIZE (CAR X))))
RMARGIN)
(<= POS2 (+ CURPOS MAXSIZE)))
(PRINC " " STREAM)
(PRIN1 (CAR X) STREAM)
(SETQ POSITION POS2))
(T (MOVETO STREAM POSITION (1+ CURPOS))
(SETQ POSITION
(PP1 (CAR X) STREAM (1+ CURPOS) RMARGIN))))
(COND ((AND (CONSP (CAR X)) (CDR X))
(SETQ POSITION (MOVETO STREAM POSITION CURPOS))))
(SETQ X (CDR X))
(GO LP)))
; PRINTMACROP is the printmacro interface routine. Note that the
; called function has the same argument list as PP1. It may either
; decide not to handle the form, by returning NIL (and not printing)
; or it may print the form and return the resulting position.
(DEFUN PRINTMACROP (X STREAM CURPOS RMARGIN &AUX MACRO)
(AND (SYMBOLP (CAR X))
(SETQ MACRO (GET (CAR X) 'PRINTMACRO))
(APPLY MACRO (LIST X STREAM CURPOS RMARGIN))))
; The remaining forms define various printmacros.
(DEFUN PP-BINDING-FORM (X STREAM POS RMAR &AUX CUR)
(SETQ CUR POS)
(COND ((AND (>= (- RMAR POS) (FLATSIZE X))
(<= (FLATSIZE X) MAXSIZE)) NIL)
((> (LENGTH X) 2)
(PRINC "(" STREAM)
(PRIN1 (CAR X) STREAM)
(PRINC " " STREAM)
(SETQ CUR
(PP1 (CADR X)
STREAM
(+ 2 POS (FLATSIZE (CAR X)))
RMAR))
(MOVETO STREAM CUR (+ POS 1))
(PP-REST (CDDR X) STREAM (+ POS 1) RMAR))))
(DEFUN PP-DO-FORM (X STREAM POS RMAR &AUX CUR POS2)
(SETQ CUR POS)
(COND ((AND (>= (- RMAR POS) (FLATSIZE X))
(<= (FLATSIZE X) MAXSIZE)) NIL)
((> (LENGTH X) 2)
(PRINC "(" STREAM)
(PRIN1 (CAR X) STREAM)
(PRINC " " STREAM)
(SETQ POS2 (+ 2 POS (FLATSIZE (CAR X))))
(SETQ CUR (PP1 (CADR X) STREAM POS2 RMAR))
(MOVETO STREAM CUR POS2)
(SETQ CUR (PP1 (CADDR X) STREAM POS2 RMAR))
(MOVETO STREAM CUR (+ POS 1))
(PP-REST (CDDDR X) STREAM (+ POS 1) RMAR))))
(DEFUN PP-DEFINING-FORM (X STREAM POS RMAR &AUX CUR)
(SETQ CUR POS)
(COND ((AND (>= (- RMAR POS) (FLATSIZE X))
(<= (FLATSIZE X) MAXSIZE)) NIL)
((> (LENGTH X) 3)
(PRINC "(" STREAM)
(PRIN1 (CAR X) STREAM)
(PRINC " " STREAM)
(PRIN1 (CADR X) STREAM)
(PRINC " " STREAM)
(SETQ CUR
(PP1 (CADDR X)
STREAM
(+ 3 POS (FLATSIZE (CAR X)) (FLATSIZE (CADR X)))
RMAR))
(MOVETO STREAM CUR (+ 3 POS))
(PP-REST (CDDDR X) STREAM (+ 3 POS) RMAR))))
(PUTPROP 'QUOTE
'(LAMBDA (X STREAM POS RMARGIN)
(COND ((AND (CDR X) (NULL (CDDR X)))
(PRINC "'" STREAM)
(PP1 (CADR X) STREAM (1+ POS) RMARGIN))))
'PRINTMACRO)
(PUTPROP 'BACKQUOTE
'(LAMBDA (X STREAM POS RMARGIN)
(COND ((AND (CDR X) (NULL (CDDR X)))
(PRINC "`" STREAM)
(PP1 (CADR X) STREAM (1+ POS) RMARGIN))))
'PRINTMACRO)
(PUTPROP 'COMMA
'(LAMBDA (X STREAM POS RMARGIN)
(COND ((AND (CDR X) (NULL (CDDR X)))
(PRINC "," STREAM)
(PP1 (CADR X) STREAM (1+ POS) RMARGIN))))
'PRINTMACRO)
(PUTPROP 'COMMA-AT
'(LAMBDA (X STREAM POS RMARGIN)
(COND ((AND (CDR X) (NULL (CDDR X)))
(PRINC ",@" STREAM)
(PP1 (CADR X) STREAM (+ POS 2) RMARGIN))))
'PRINTMACRO)
(PUTPROP 'FUNCTION
'(LAMBDA (X STREAM POS RMARGIN)
(COND ((AND (CDR X) (NULL (CDDR X)))
(PRINC "#'" STREAM)
(PP1 (CADR X) STREAM (+ POS 2) RMARGIN))))
'PRINTMACRO)
(PUTPROP 'PROG
'PP-BINDING-FORM
'PRINTMACRO)
(PUTPROP 'PROG*
'PP-BINDING-FORM
'PRINTMACRO)
(PUTPROP 'LET
'PP-BINDING-FORM
'PRINTMACRO)
(PUTPROP 'LET*
'PP-BINDING-FORM
'PRINTMACRO)
(PUTPROP 'LAMBDA
'PP-BINDING-FORM
'PRINTMACRO)
(PUTPROP 'MACRO
'PP-BINDING-FORM
'PRINTMACRO)
(PUTPROP 'DO 'PP-DO-FORM 'PRINTMACRO)
(PUTPROP 'DO*
'PP-DO-FORM
'PRINTMACRO)
(PUTPROP 'DEFUN
'PP-DEFINING-FORM
'PRINTMACRO)
(PUTPROP 'DEFMACRO
'PP-DEFINING-FORM
'PRINTMACRO)